// index.js - 模块主入口
const fs = require("fs");
const path = require("path");
const { execSync } = require("child_process");
const { rimrafSync } = require("rimraf");

module.exports = {
  downloadAndBuild: async function (repoUrl, targetDir, buildDir) {
    try {
      // 1. 克隆GitHub仓库
      await this.cloneRepo(repoUrl, buildDir);

      // 2. 安装依赖并构建
      await this.installAndBuild(buildDir);

      // 3. 拷贝构建结果到目标目录
      await this.copyBuildResult(buildDir, targetDir);

      // 4. 清理临时文件
      await this.cleanup(buildDir);

      console.log("所有操作完成！");
    } catch (error) {
      console.error("处理过程中出错:", error);
    }
  },
  cloneRepo: async function (repoUrl, buildDir) {
    try {
      console.log("开始克隆仓库...");

      // 1. 检查Git安装
      console.log("检查Git安装...");
      execSync("git --version", { stdio: "inherit" });

      // 2. 清理目标目录（加强版）
      console.log("准备构建目录...");
      if (fs.existsSync(buildDir)) {
        console.log("删除现有目录...");
        await this.forceDelete(buildDir); // 使用下面的强制删除函数
      }

      // 3. 执行克隆
      console.log(`执行克隆命令: git clone ${repoUrl} ${buildDir}`);
      execSync(`git clone ${repoUrl} ${buildDir}`, { stdio: "inherit" });

      // 4. 验证结果
      if (!fs.existsSync(path.join(buildDir, ".git"))) {
        throw new Error("克隆成功但未检测到.git目录");
      }
      console.log("仓库克隆成功！");
    } catch (error) {
      throw new Error(`克隆失败: ${error.message}`);
    }
  },

  deleteDirectoryRecursive: function (directory) {
    if (!fs.existsSync(directory)) return;

    // 方法1：优先使用 rimraf（最可靠方式）
    try {
      rimrafSync(directory, {
        maxBusyTries: 5, // 最大重试次数
        emfileWait: 1000, // 文件忙等待时间(ms)
        glob: false, // 禁用glob模式提升性能
      });
      return;
    } catch (rimrafError) {
      console.warn(`[阶段1] rimraf删除失败: ${rimrafError.message}`);
    }

    // 方法2：Windows专用强制解除占用
    if (process.platform === "win32") {
      try {
        // 2.1 杀死可能占用文件的进程
        execSync(`taskkill /F /IM node.exe /T`, { stdio: "ignore" });
        execSync(
          `powershell -Command "Get-Process | Where-Object { $_.Path -like '*${directory}*' } | Stop-Process -Force"`,
          {
            stdio: "ignore",
          }
        );

        // 2.2 使用系统命令强制删除
        execSync(`rd /s /q "${directory}"`, { stdio: "ignore" });
        return;
      } catch (winError) {
        console.warn(`[阶段2] Windows强制删除失败: ${winError.message}`);
      }
    }

    // 方法3：递归删除+重试机制
    const maxRetries = 3;
    const retryDelay = 500; // 重试延迟(ms)

    const tryDelete = (currentPath, retryCount = 0) => {
      try {
        const stat = fs.lstatSync(currentPath);

        if (stat.isDirectory()) {
          // 递归处理子目录
          fs.readdirSync(currentPath).forEach((file) => {
            tryDelete(path.join(currentPath, file));
          });
          fs.rmdirSync(currentPath);
        } else {
          // 删除文件
          fs.unlinkSync(currentPath);
        }
      } catch (error) {
        if (retryCount >= maxRetries) {
          throw new Error(`删除失败: ${currentPath} (原因: ${error.message})`);
        }

        // Windows特定处理
        if (
          process.platform === "win32" &&
          (error.code === "EBUSY" || error.code === "EPERM")
        ) {
          console.warn(`文件被锁定，等待后重试: ${currentPath}`);
          setTimeout(
            () => tryDelete(currentPath, retryCount + 1),
            retryDelay * (retryCount + 1)
          );
        } else {
          throw error;
        }
      }
    };

    // 方法4：终极fallback - 重命名+延迟删除
    if (process.platform === "win32") {
      try {
        const trashDir = `${directory}_trash_${Date.now()}`;
        fs.renameSync(directory, trashDir);
        setTimeout(() => {
          try {
            rimrafSync(trashDir);
          } catch {}
        }, 3000);
        return;
      } catch (renameError) {
        console.warn(`[阶段3] 重命名方案失败: ${renameError.message}`);
      }
    }

    // 方法5：Linux/Mac备用方案
    try {
      execSync(`rm -rf "${directory}"`, { stdio: "ignore" });
    } catch (finalError) {
      throw new Error(`所有删除方式均失败，请手动删除:
    1. 关闭所有IDE和终端
    2. 检查是否有node.exe进程残留
    3. 手动删除目录: ${directory}
    原错误: ${finalError.message}`);
    }
  },
  // 强制删除目录
  forceDelete: async function (dir) {
    try {
      // 方法1：优先使用Node.js原生方法
      if (fs.existsSync(dir)) {
        await fs.promises.rm(dir, {
          recursive: true,
          force: true,
          maxRetries: 3,
          retryDelay: 300,
        });
      }
    } catch (err) {
      // 方法2：回退到系统命令
      if (process.platform === "win32") {
        execSync(`rd /s /q "${path.resolve(dir)}"`, { stdio: "ignore" });
      } else {
        execSync(`rm -rf "${path.resolve(dir)}"`, { stdio: "ignore" });
      }
    }
  },
  safeDelete: function (directory) {
    try {
      // 方法1: 使用 rimraf
      rimrafSync(directory);

      // 方法2: Windows 系统命令（备用）
      if (process.platform === "win32") {
        execSync(`taskkill /F /IM node.exe /T`, { stdio: "ignore" });
        execSync(`rd /s /q "${directory}"`, { stdio: "ignore" });
      }
    } catch (error) {
      console.warn(`删除目录失败: ${directory}`);
      console.warn("请手动关闭所有可能占用该目录的程序后重试");
    }
  },
  installAndBuild: function (buildDir) {
    // 实现构建逻辑
    console.log("开始安装依赖并构建...");

    try {
      // 进入构建目录
      process.chdir(buildDir);

      // 检查package.json是否存在
      if (!fs.existsSync("package.json")) {
        throw new Error("package.json不存在，无法构建");
      }

      // 安装依赖
      execSync("npm install", { stdio: "inherit" });

      // 执行构建脚本
      if (this.hasScript("build")) {
        execSync("npm run build", { stdio: "inherit" });
      } else {
        console.warn("package.json中没有build脚本，跳过构建步骤");
      }

      console.log("依赖安装与构建完成！");
    } catch (error) {
      throw new Error(`构建过程失败: ${error.message}`);
    } finally {
      // 返回原始工作目录
      process.chdir(path.join(__dirname, ".."));
    }
  },
  hasScript: function (scriptName) {
    const pkgPath = path.join(process.cwd(), "package.json");
    if (fs.existsSync(pkgPath)) {
      const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
      return pkg.scripts && pkg.scripts[scriptName];
    }
    return false;
  },
  copyBuildResult: function (buildDir, targetDir) {
    // 实现拷贝逻辑
    console.log("开始拷贝构建结果...");

    // 确定构建输出目录（通常是dist或build）
    const possibleDirs = ["dist", "build", "out", "public"];
    let buildOutputDir = "";

    for (const dir of possibleDirs) {
      const fullPath = path.join(buildDir, dir);
      if (fs.existsSync(fullPath)) {
        buildOutputDir = fullPath;
        break;
      }
    }
    console.log(`构建输出目录: ${buildOutputDir}`);
    if (!buildOutputDir) {
      throw new Error("未找到构建输出目录，请检查项目配置");
    }

    // 如果目标目录已存在则先备份
    if (fs.existsSync(targetDir)) {
      const backupDir = `${targetDir}_backup_${new Date()
        .toISOString()
        .replace(/[:.]/g, "-")}`;
      fs.renameSync(targetDir, backupDir);
      console.log(`已备份原有目录到: ${backupDir}`);
    }

    // 创建目标目录
    fs.mkdirSync(targetDir, { recursive: true });

    // 拷贝文件
    this.copyDirectoryRecursive(buildOutputDir, targetDir);
    console.log("构建结果拷贝完成！");
  },

  copyDirectoryRecursive: function (src, dest) {
    if (!fs.existsSync(src)) {
      throw new Error(`源目录不存在: ${src}`);
    }

    // 确保目标目录存在
    if (!fs.existsSync(dest)) {
      fs.mkdirSync(dest, { recursive: true });
    }

    // 遍历源目录
    const entries = fs.readdirSync(src);

    for (const entry of entries) {
      const srcPath = path.join(src, entry);
      const destPath = path.join(dest, entry);

      const stat = fs.statSync(srcPath);

      if (stat.isDirectory()) {
        // 递归拷贝子目录
        this.copyDirectoryRecursive(srcPath, destPath);
      } else {
        // 拷贝文件
        fs.copyFileSync(srcPath, destPath);
      }
    }
  },
  cleanup: function (buildDir) {
    // 实现清理逻辑
    console.log("开始清理临时文件...");

    try {
      if (fs.existsSync(buildDir)) {
        this.deleteDirectoryRecursive(buildDir);
        console.log("临时文件清理完成！");
      }
    } catch (error) {
      console.error("清理过程中出错:", error);
    }
  },
};
